"""
API Middleware
API中间件 - 认证、错误处理、请求日志
"""

import time
import uuid
from typing import Optional, Dict, Any
from datetime import datetime

from fastapi import Request, Response, HTTPException, status
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.cors import CORSMiddleware
import structlog

from ..core.config import settings
from ..core.exceptions import (
    MediaCreateException,
    ValidationError,
    AuthenticationError,
    PermissionDeniedError,
    UserNotFoundError,
    ContentNotFoundError,
    FolderNotFoundError,
    TagNotFoundError,
)
from ..models.system_log import LogLevel, LogCategory, create_log_entry
from .auth import get_current_user, oauth2_scheme

# 配置结构化日志
logger = structlog.get_logger(__name__)


class RequestLoggingMiddleware(BaseHTTPMiddleware):
    """请求日志中间件"""
    
    async def dispatch(self, request: Request, call_next):
        """处理请求和响应"""
        request_id = str(uuid.uuid4())
        start_time = time.time()
        
        # 添加请求ID到请求状态
        request.state.request_id = request_id
        
        # 记录请求开始
        logger.info(
            "Request started",
            request_id=request_id,
            method=request.method,
            url=str(request.url),
            client_ip=get_client_ip(request),
            user_agent=request.headers.get("user-agent", "")
        )
        
        try:
            # 处理请求
            response = await call_next(request)
            
            # 计算处理时间
            process_time = time.time() - start_time
            
            # 记录响应
            logger.info(
                "Request completed",
                request_id=request_id,
                method=request.method,
                url=str(request.url),
                status_code=response.status_code,
                process_time=round(process_time, 3)
            )
            
            # 添加请求ID到响应头
            response.headers["X-Request-ID"] = request_id
            
            return response
            
        except Exception as e:
            # 记录异常
            process_time = time.time() - start_time
            logger.error(
                "Request failed with exception",
                request_id=request_id,
                method=request.method,
                url=str(request.url),
                error=str(e),
                error_type=type(e).__name__,
                process_time=round(process_time, 3)
            )
            
            # 重新抛出异常
            raise


class ErrorHandlingMiddleware(BaseHTTPMiddleware):
    """错误处理中间件"""
    
    async def dispatch(self, request: Request, call_next):
        """处理错误"""
        try:
            response = await call_next(request)
            return response
            
        except BaseAppError as e:
            # 处理应用自定义错误
            logger.warning(
                "Application error occurred",
                request_id=getattr(request.state, 'request_id', 'unknown'),
                error_code=e.error_code,
                message=str(e),
                details=e.details
            )
            
            return JSONResponse(
                status_code=e.status_code,
                content={
                    "success": False,
                    "error": {
                        "code": e.error_code,
                        "message": str(e),
                        "details": e.details
                    },
                    "request_id": getattr(request.state, 'request_id', 'unknown')
                }
            )
            
        except HTTPException as e:
            # 处理FastAPI HTTP异常
            logger.warning(
                "HTTP exception occurred",
                request_id=getattr(request.state, 'request_id', 'unknown'),
                status_code=e.status_code,
                detail=e.detail
            )
            
            return JSONResponse(
                status_code=e.status_code,
                content={
                    "success": False,
                    "error": {
                        "code": f"HTTP_{e.status_code}",
                        "message": e.detail
                    },
                    "request_id": getattr(request.state, 'request_id', 'unknown')
                }
            )
            
        except Exception as e:
            # 处理未预期的异常
            request_id = getattr(request.state, 'request_id', 'unknown')
            logger.error(
                "Unexpected error occurred",
                request_id=request_id,
                error=str(e),
                error_type=type(e).__name__,
                exc_info=True
            )
            
            return JSONResponse(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                content={
                    "success": False,
                    "error": {
                        "code": "INTERNAL_SERVER_ERROR",
                        "message": "An internal server error occurred",
                        "request_id": request_id
                    }
                }
            )


class AuthenticationMiddleware(BaseHTTPMiddleware):
    """认证中间件"""
    
    def __init__(self, app, exclude_paths: Optional[list] = None):
        super().__init__(app)
        self.exclude_paths = exclude_paths or [
            "/docs",
            "/openapi.json",
            "/health",
            "/api/v1/auth/login",
            "/api/v1/auth/register",
        ]
    
    async def dispatch(self, request: Request, call_next):
        """处理认证"""
        # 检查是否需要认证
        if self._should_skip_auth(request):
            response = await call_next(request)
            return response
        
        # 获取认证头
        authorization = request.headers.get("authorization")
        if not authorization:
            logger.warning(
                "Missing authorization header",
                request_id=getattr(request.state, 'request_id', 'unknown'),
                url=str(request.url)
            )
            
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "success": False,
                    "error": {
                        "code": "MISSING_AUTH_HEADER",
                        "message": "Authorization header is required"
                    }
                }
            )
        
        try:
            # 提取token
            scheme, token = authorization.split(" ", 1)
            if scheme.lower() != "bearer":
                raise ValueError("Invalid authentication scheme")
            
            # 这里可以添加token验证逻辑
            # 为了简化，我们假设token是有效的
            request.state.user_token = token
            
            response = await call_next(request)
            return response
            
        except ValueError as e:
            logger.warning(
                "Invalid authorization header format",
                request_id=getattr(request.state, 'request_id', 'unknown'),
                error=str(e)
            )
            
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "success": False,
                    "error": {
                        "code": "INVALID_AUTH_HEADER",
                        "message": "Invalid authorization header format"
                    }
                }
            )
        
        except Exception as e:
            logger.error(
                "Authentication error",
                request_id=getattr(request.state, 'request_id', 'unknown'),
                error=str(e)
            )
            
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "success": False,
                    "error": {
                        "code": "AUTHENTICATION_FAILED",
                        "message": "Authentication failed"
                    }
                }
            )
    
    def _should_skip_auth(self, request: Request) -> bool:
        """检查是否应该跳过认证"""
        path = request.url.path
        
        # 检查路径是否在排除列表中
        for exclude_path in self.exclude_paths:
            if path.startswith(exclude_path):
                return True
        
        # 检查是否是静态文件
        if path.startswith("/static/") or path.endswith((".css", ".js", ".png", ".jpg", ".ico")):
            return True
        
        return False


class RateLimitMiddleware(BaseHTTPMiddleware):
    """速率限制中间件"""
    
    def __init__(self, app, requests_per_minute: int = 60):
        super().__init__(app)
        self.requests_per_minute = requests_per_minute
        self.request_counts: Dict[str, list] = {}
    
    async def dispatch(self, request: Request, call_next):
        """处理速率限制"""
        client_ip = get_client_ip(request)
        current_time = time.time()
        
        # 清理旧的请求记录
        if client_ip in self.request_counts:
            self.request_counts[client_ip] = [
                timestamp for timestamp in self.request_counts[client_ip]
                if current_time - timestamp < 60
            ]
        else:
            self.request_counts[client_ip] = []
        
        # 检查是否超过限制
        if len(self.request_counts[client_ip]) >= self.requests_per_minute:
            logger.warning(
                "Rate limit exceeded",
                request_id=getattr(request.state, 'request_id', 'unknown'),
                client_ip=client_ip,
                request_count=len(self.request_counts[client_ip])
            )
            
            return JSONResponse(
                status_code=status.HTTP_429_TOO_MANY_REQUESTS,
                content={
                    "success": False,
                    "error": {
                        "code": "RATE_LIMIT_EXCEEDED",
                        "message": f"Rate limit exceeded. Maximum {self.requests_per_minute} requests per minute."
                    }
                }
            )
        
        # 记录当前请求
        self.request_counts[client_ip].append(current_time)
        
        response = await call_next(request)
        return response


class CORSMiddlewareConfig:
    """CORS配置"""
    
    @staticmethod
    def create_cors_middleware(app) -> CORSMiddleware:
        """创建CORS中间件"""
        return CORSMiddleware(
            app=app,
            allow_origins=settings.security.cors_origins,
            allow_credentials=True,
            allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
            allow_headers=["*"],
            expose_headers=["X-Request-ID"]
        )


class SecurityHeadersMiddleware(BaseHTTPMiddleware):
    """安全头中间件"""
    
    async def dispatch(self, request: Request, call_next):
        """添加安全头"""
        response = await call_next(request)
        
        # 添加安全头
        response.headers["X-Content-Type-Options"] = "nosniff"
        response.headers["X-Frame-Options"] = "DENY"
        response.headers["X-XSS-Protection"] = "1; mode=block"
        response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
        response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
        
        return response


# 辅助函数
def get_client_ip(request: Request) -> str:
    """获取客户端IP地址"""
    # 检查代理头
    forwarded_for = request.headers.get("X-Forwarded-For")
    if forwarded_for:
        return forwarded_for.split(",")[0].strip()
    
    real_ip = request.headers.get("X-Real-IP")
    if real_ip:
        return real_ip
    
    # 返回直接连接的IP
    if hasattr(request.client, 'host'):
        return request.client.host
    
    return "unknown"


def create_middleware_stack(app):
    """创建中间件栈"""
    # 添加中间件的顺序很重要
    
    # 1. CORS中间件（最外层）
    app = CORSMiddlewareConfig.create_cors_middleware(app)
    
    # 2. 安全头中间件
    app = SecurityHeadersMiddleware(app)
    
    # 3. 速率限制中间件
    app = RateLimitMiddleware(app, requests_per_minute=60)
    
    # 4. 请求日志中间件
    app = RequestLoggingMiddleware(app)
    
    # 5. 错误处理中间件
    app = ErrorHandlingMiddleware(app)
    
    # 6. 认证中间件（最内层，最后执行）
    app = AuthenticationMiddleware(app)
    
    return app


# 导出中间件类和函数
__all__ = [
    "RequestLoggingMiddleware",
    "ErrorHandlingMiddleware", 
    "AuthenticationMiddleware",
    "RateLimitMiddleware",
    "SecurityHeadersMiddleware",
    "create_middleware_stack",
    "get_client_ip"
]